package com.example.dingdong.rest;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.dingdong.daomain.BasicUserEntity;
import com.example.dingdong.daomain.RoleEntity;
import com.example.dingdong.daomain.RouterEntity;
import com.example.dingdong.service.BasicUserService;
import com.example.dingdong.service.RouterService;
import com.example.dingdong.util.CheckRequestUtil;
import com.example.dingdong.util.CheckUtils;
import com.example.dingdong.util.ExceptionType;
import com.example.dingdong.util.MyException;

@RestController
@RequestMapping(value = "/web/rest/router/")
public class RouterRest {

	private static final Logger log = LoggerFactory.getLogger(RouterRest.class);

	@Autowired
	private RouterService routerService;

	@Autowired
	private BasicUserService userService;

	/**
	 * 添加路由
	 */
	@PostMapping(value = "addRouter", consumes = "application/json")
	public JSONObject addRouter(@RequestBody String reqStr) {
		log.info("addRouter 添加路由:" + reqStr);
		/**
		 * 预返回数据
		 */
		JSONObject returnData = new JSONObject();
		JSONObject response = new JSONObject();
		returnData.put("cmd", "addRouter");
		returnData.put("type", "response");
		returnData.put("response", response);

		try {
			JSONObject request = CheckRequestUtil.checkReqInterface(reqStr, "addRouter");

			// 1、获取所有传入数据
			Integer id = request.getInteger("id");
			Integer sort = request.getInteger("sort");
			String path = request.getString("path");
			String component = request.getString("component");
			String name = request.getString("name");
			String icon = request.getString("icon");
			Boolean strict = request.getBoolean("strict");
			Boolean exact = request.getBoolean("exact");
			String redirect = request.getString("redirect");

			// 2、校验前端数据
			if (StringUtils.isEmpty(sort)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入排序!");
			}
			if (StringUtils.isEmpty(path)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入路径!");
			}

			// 3、创建路由对象
			RouterEntity router = new RouterEntity(path, sort, component, name, icon, strict, exact, redirect);

			// 4、保存路由对象(id 存在则绑定父节点，否则直接存路由)
			if (id != null && id > 0) {
				RouterEntity parentRouter = routerService.getRouter(id, true);
				routerService.routerBind(parentRouter, router);
			} else {
				routerService.saveRouter(router);
			}

			/**
			 * 返回前端数据
			 */
			response.put("res", true);
		} catch (MyException e) {
			log.error("addRouter:" + e.getReason());
			response.put("res", false);
			response.put("exception", e.getReason());
		} catch (Exception e) {
			log.error("addRouter:");
			log.error("error", e);
			response.put("res", false);
			response.put("exception", e.getMessage());
		}
		log.info("addRouter 接口方法调用完成");
		return returnData;
	}

	/**
	 * 删除路由
	 */
	@PostMapping(value = "deleteRouter", consumes = "application/json")
	public JSONObject deleteRouter(@RequestBody String reqStr) {
		log.info("deleteRouter 删除路由:" + reqStr);
		/**
		 * 预返回数据
		 */
		JSONObject returnData = new JSONObject();
		JSONObject response = new JSONObject();
		returnData.put("cmd", "deleteRouter");
		returnData.put("type", "response");
		returnData.put("response", response);

		try {
			JSONObject request = CheckRequestUtil.checkReqInterface(reqStr, "deleteRouter");

			// 1、获取所有传入数据
			Integer id = request.getInteger("id");

			// 2、校验前端数据
			if (StringUtils.isEmpty(id)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入路由结点!");
			}

			// 3、查找路由结点
			RouterEntity router = routerService.getRouter(id, true);
			if (router == null) {
				throw new MyException(ExceptionType.OperationError, "路由下存在子节点无法进行删除!");
			}

			// 4、存在子节点不允许删除
			List<RouterEntity> children = router.getChildren();
			for (int i = 0; i < children.size(); i++) {
				RouterEntity childrenRouter = children.get(i);
				if (childrenRouter.isDelFlag()) {
					throw new MyException(ExceptionType.OperationError, "路由下存在子节点无法进行删除!");
				}
			}

			// 5、路由绑定了角色不允许删除
			List<RoleEntity> roleList = router.getJoinRoleList();
			for (int i = 0; i < roleList.size(); i++) {
				RoleEntity role = roleList.get(i);
				if (role.isDelFlag()) {
					throw new MyException(ExceptionType.OperationError, "路由绑定了角色无法进行删除!");
				}
			}

			// 6、删除路由
			routerService.delRouter(router);

			/**
			 * 返回前端数据
			 */
			response.put("res", true);
		} catch (MyException e) {
			log.error("deleteRouter:" + e.getReason());
			response.put("res", false);
			response.put("exception", e.getReason());
		} catch (Exception e) {
			log.error("deleteRouter:");
			log.error("error", e);
			response.put("res", false);
			response.put("exception", e.getMessage());
		}
		log.info("deleteRouter 接口方法调用完成");
		return returnData;
	}
	/**
	 * 查询路由
	 */
	@PostMapping(value = "findRouter", consumes = "application/json")
	public JSONObject findRouter(@RequestBody String reqStr) {
		log.info("findRouter 查询路由:" + reqStr);
		/**
		 * 预返回数据
		 */
		JSONObject returnData = new JSONObject();
		JSONObject response = new JSONObject();
		returnData.put("cmd", "findRouter");
		returnData.put("type", "response");
		returnData.put("response", response);

		try {
			JSONObject request = CheckRequestUtil.checkReqInterface(reqStr, "findRouter");
			// 1、获取前端数据(true-获取登录用户绑定的路由，false-获取所有路由)
			boolean isLogin = request.getBooleanValue("isLogin");

			// 2、查询路由实体
			List<RouterEntity> routerList = new ArrayList<>();
			if (isLogin) {
				BasicUserEntity basicData = userService.getLoginUser();
				RoleEntity role = (basicData == null) ? null : basicData.getRoleEntity();
				routerList = (role == null) ? new ArrayList<>() : role.getRouterList();
			} else {
				routerList = routerService.getRouterList();
			}

			// 3、查找所有父节点和子节点数据
			JSONArray message = new JSONArray();
			for (int i = 0; i < routerList.size(); i++) {
				RouterEntity router = routerList.get(i);
				RouterEntity parentRouter = router.getParent();
				JSONObject routerInfo = (JSONObject) JSONObject.toJSON(router);
				routerInfo.put("parentId", (parentRouter == null) ? -1 : parentRouter.getId());
				routerInfo.put("key", router.getId());
				message.add(routerInfo);
			}

			// 4、生成对应数据结构x
			message = CheckUtils.listToTree(message);

			// 5、排序
			message.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("sort")));

			/**
			 * 返回前端数据
			 */
			response.put("res", true);
			response.put("message", message);
		} catch (MyException e) {
			log.error("findRouter:" + e.getReason());
			response.put("res", false);
			response.put("exception", e.getReason());
		} catch (Exception e) {
			log.error("findRouter:", e);
			response.put("res", false);
			response.put("exception", e.getMessage());
		}
		log.info("findRouter 接口方法调用完成");
		return returnData;
	}


	/**
	 * 编辑路由
	 */
	@PostMapping(value = "editRouter", consumes = "application/json")
	public JSONObject editRouter(@RequestBody String reqStr) {
		log.info("editRouter 编辑路由:" + reqStr);
		/**
		 * 预返回数据
		 */
		JSONObject returnData = new JSONObject();
		JSONObject response = new JSONObject();
		returnData.put("cmd", "editRouter");
		returnData.put("type", "response");
		returnData.put("response", response);

		try {
			JSONObject request = CheckRequestUtil.checkReqInterface(reqStr, "editRouter");

			// 1、获取所有传入数据
			Integer parentId = request.getInteger("parentId");
			Integer id = request.getInteger("id");
			String path = request.getString("path");
			Integer sort = request.getInteger("sort");
			String component = request.getString("component");
			String name = request.getString("name");
			String icon = request.getString("icon");
			Boolean strict = request.getBoolean("strict");
			Boolean exact = request.getBoolean("exact");
			String redirect = request.getString("redirect");

			// 2、校验前端数据
			if (StringUtils.isEmpty(id)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入路由!");
			}
			if (StringUtils.isEmpty(path)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入路径!");
			}
			if (StringUtils.isEmpty(sort)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入排序!");
			}
			if (StringUtils.isEmpty(parentId)) {
				throw new MyException(ExceptionType.NotFoundField, "请传入父节点!");
			}
			if (Objects.equals(id, parentId)) {
				throw new MyException(ExceptionType.NotFoundField, "父节点与子节点不能重复!");
			}

			// 3、查找路由对象
			RouterEntity router = routerService.getRouter(id, true);
			if (router == null) {
				throw new MyException(ExceptionType.LookupDatabaseIsEmpty, "查询路由失败!");
			}

			// 4、更新路由数据
			routerService.updateAndChangeBindRouter(parentId, router, path, sort, component, name, icon, strict, exact,
					redirect);

			/**
			 * 返回前端数据
			 */
			response.put("res", true);
		} catch (MyException e) {
			log.error("editRouter:" + e.getReason());
			response.put("res", false);
			response.put("exception", e.getReason());
		} catch (Exception e) {
			log.error("editRouter:", e);
			response.put("res", false);
			response.put("exception", e.getMessage());
		}
		log.info("editRouter 接口方法调用完成");
		return returnData;
	}

	/**
	 * 获取结点及子结点所有信息
	 */
	public JSONObject getNodeAndChildrenNodeInfo(RouterEntity parentRouter) {
		JSONObject parentRoObject = new JSONObject();

		if (parentRouter == null || !parentRouter.isDelFlag()) {
			return parentRoObject;
		}

		parentRoObject = (JSONObject) JSONObject.toJSON(parentRouter);
		RouterEntity parent = parentRouter.getParent();
		int parentId = (parent == null) ? -1 : parent.getId();
		parentRoObject.put("key", parentRouter.getId());
		parentRoObject.put("parentId", parentId);

		JSONArray childArr = new JSONArray();

		for (RouterEntity temp : parentRouter.getChildren()) {
			if (!temp.isDelFlag()) {
				continue;
			}

			if (temp.getChildren().size() > 0) {
				childArr.add(getNodeAndChildrenNodeInfo(temp));
			} else {
				JSONObject childrenInfo = (JSONObject) JSONObject.toJSON(temp);
				childrenInfo.put("key", temp.getId());
				childrenInfo.put("parentId", parentRouter.getId());
				childArr.add(childrenInfo);
			}
		}

		childArr.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("sort")));
		parentRoObject.put("children", childArr);
		return parentRoObject;
	}

	/**
	 * 获取结点及子节点
	 */
	public List<RouterEntity> getNodeAndChildrenNode(RouterEntity parentRouter) {
		List<RouterEntity> routerList = new ArrayList<>();

		if (parentRouter == null || !parentRouter.isDelFlag()) {
			return routerList;
		}
		routerList.add(parentRouter);

		List<RouterEntity> childrenRouterList = parentRouter.getChildren();
		for (int i = 0; i < childrenRouterList.size(); i++) {
			RouterEntity router = childrenRouterList.get(i);
			if (!router.isDelFlag()) {
				continue;
			}

			if (router.getChildren().size() > 0) {
				routerList.addAll(getNodeAndChildrenNode(router));
			} else {
				routerList.add(router);
			}
		}

		return routerList;
	}

}